package framework;

import java.io.DataInputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * Filter that reads data from a file.
 */
public class FileDataSource extends FilterFramework {

	/**
	 * The file path of the file to read.
	 */
	private String filePath;

	/**
	 * Constructor
	 * 
	 * @param filePath The file path of the file to read.
	 */
	public FileDataSource(String filePath) {
		// creates a filter with 0 inputs and 1 output
		super(0, 1);
		this.filePath = filePath;
	}

	/**
	 * The main method of the filter. Starts when the thread is launched
	 */
	@Override
	public void run() {

		int bytesRead = 0; // Number of bytes read from the input file.
		int bytesWritten = 0; // Number of bytes written to the stream.
		DataInputStream in = null; // File stream reference.
		byte dataByte; // The byte of data read from the file

		try {
			/***********************************************************************************
			 * Here we open the file and write a message to the terminal.
			 ***********************************************************************************/

			in = new DataInputStream(new FileInputStream(this.filePath));
			System.out.println("\n" + this.getName()
					+ "::Source reading file...");

			/***********************************************************************************
			 * Here we read the data from the file and send it out the filter's
			 * output port one byte at a time. The loop stops when it encounters
			 * an EOFExecption.
			 ***********************************************************************************/

			while (true) {
				dataByte = in.readByte();
				bytesRead++;
				WriteFilterOutputPort(dataByte, 0);
				bytesWritten++;

			} // while

		} // try

		/***********************************************************************************
		 * The following exception is raised when we hit the end of input file.
		 * Once we reach this point, we close the input file, close the filter
		 * ports and exit.
		 ***********************************************************************************/

		catch (EOFException eoferr) {
			System.out.println("\n" + this.getName()
					+ "::End of file reached...");
			try {
				if (in != null) {
					in.close();
				}
				ClosePorts();
				System.out.println("\n" + this.getName()
						+ "::Read file complete, bytes read::" + bytesRead
						+ " bytes written: " + bytesWritten);

			}
			/***********************************************************************************
			 * The following exception is raised should we have a problem
			 * closing the file.
			 ***********************************************************************************/
			catch (Exception closeErr) {
				System.out.println("\n" + this.getName()
						+ "::Problem closing input data file::" + closeErr);
			} // catch

		} // catch

		/***********************************************************************************
		 * The following exception is raised should we have a problem opening
		 * the file.
		 ***********************************************************************************/

		catch (IOException iox) {
			System.out.println("\n" + this.getName()
					+ "::Problem reading input data file::" + iox);
		} // catch

	}
}
